<?php /**
*DomainObject an abstract blue print for any object in the system.
*
*@package Business
*@author Garry Willits && Matt Zandstra (Mostly Garry)
*@copyright 2005
*@version 1.1
*/
abstract class DomainObject{
/**
*@var int
*/
protected $id;
/**
*@var string
*/
protected $type;
/**
*@var string
*/
protected $value;
/**
 * 
 * virtual properties of this object
 * @var unknown_type
 */
protected $properties = array();
/**
 * The properties being saved
*@var array
*/
protected $properties_to_save = array();
/**
 * 
 * The mapper dao
 * @var unknown_type
 */
protected $mapper;

/**
 * 
 * the types of the properties
 * @var array
 */
protected $property_types = array();
/**
 * 
 * Any properties that have changed
 * @var unknown_type
 */
protected $changed = array();
/**
 * 
 * Where child objects are kept
 * @var unknown_type
 */
protected $anonymous;
/**
 * 
 * A list of child ids
 * @var unknown_type
 */
protected $childoids = array();
/**
 * 
 * Used to cache lazy loaded objects
 * @var unknown_type
 */
protected $cached = array();
/**
 * 
 * Boolean used during initialisation
 * @var unknown_type
 */
public $initialising;

public function __construct(  ){

}
/**
 * 
 * grab any attempt to change a property
 * @param unknown_type $prop
 * @param unknown_type $value
 */
public function __set( $prop, $value){
	if( $value instanceof DomainObject ){
		$this->properties[ $prop ]=$value;
		$this->changed[ $prop ]="oid_".$value->oid;
	}
	elseif( is_object( $value ) ){
		throw new InvalidArgumentException("Only objects of type domain object may be added to Domain Objects", 102);
	}
	else if ( !is_object($value)){
		$this->properties[ $prop ] = $value;
		$this->changed[ $prop ]= $value;
	}
	if( $this->initialising ){
		return;
	} 
	$this->markChanged();
	
}
/**
 * 
 * get a virtual property ( Must be Domain Object );
 * @param unknown_type $prop
 */
public function __get( $prop ){
	// check if this is actually object 
	// lazy loading
	// two scenarios, one object is anonymous
	// other that it has a virtual property name
	if( array_key_exists( $prop,$this->properties ) && substr($this->properties[ $prop ],0,3)=="oid" ){
		$retDat=$this->mapper->GetByIds( substr( $this->properties[ $prop ],4) );
		// it should always be first element in associative array
		if( $retDat[ 0 ] instanceof ContentDao ){
			$this->properties[ $prop ] = $retDat[ 0 ];
			return $this->properties[ $prop ];
		}
		
	}
	if( isset( $this->properties[ $prop ] ) )return $this->properties[ $prop ];
	// if not it must be normal property and should be defined

}
/**
*set Value
*@return string
*/
public function getValue( ){
return $this->value;
}
/**
*set Value
*@param string
*/
public function setValue( $value ){
$this->value = $value;
}
/**
*set Name
*@param string
*/
public function setName( $value ){
$this->properties['name'] = $value;
}
/**
*get Id
*@return int
*/
public function getID( ){
return $this->id;
}
/**
*set Id (should only happen once)
*@param int
*/
public function setID( $id ){
$this->id = $id;
}
/**
*sets an object mapper
*/
abstract public function setMapper();
/**
*return an object mapper
*@return ObjectMapper
*/
public function mapper(){
return $this->mapper;
}

/**
*marks this object as new and therefore must be saved in a certain way
*/
public function markNew( ){

ObjectWatcher::addNew( $this );
}
/**
*marks this object as changed and therefore must be saved in a certain way
*/
public function markChanged( ){
ObjectWatcher::addChanged( $this );
}
/**
*marks this object as unchanged and therefore not to be saved
*/
public function markUnChanged( ){

ObjectWatcher::addUnchanged( $this );
}
/**
*marks this object as ready for deletion
*/
public function delete( ){
ObjectWatcher::addDelete( $this );
}
/**
 * 
 * Get the properties describer
 */
public function GetPropertyTypes(){
	return $this->property_types;
}
/**
 * 
 * Add a set of properties from Mapper probably
 * @param unknown_type $props
 */
public function addProperties( $props ){
		
	foreach ( $props as $prop => $val ){	
		if( property_exists(get_class($this), $prop) ){
			$this->$prop = $val;
		}
		else {
		$this->properties[ $prop ] = $val;
		}
	}
}
/**
 * 
 * Get the properties 
 */
public function GetProperties(){
	foreach( array_keys( $this->property_types ) as $key ){
		$this->properties_to_save [ $key ] = $this->$key;
	}
	return $this->properties_to_save ;
}

/**
 * 
 * Get the changed properties 
 */
public function GetChangedProperties(){
	$retarray = array();
	foreach ( $this->changed as $key => $val ){
		$retarray[ $key ] = $val;
	}
	return $retarray;
}
/**
*get type
*@return int
*/
public function getType( ){
return $this->type;
}
/**
*set type
*@param string
*/
public function setType( $type ){
$this->type = $type;
}
/**
*add an object to this
*@param DomainObject
*/
public function addObject( $object ){
$objects = func_get_args();
    foreach( $objects as $in ){
    $this->doAddObject( $in );
    }
}
/**
 * 
 * inherited implementation method
 * @param unknown_type $object
 */
abstract protected function doAddObject( $object );
/**
*get child objects
*@return Collection
*/
public function getObjects( ){
$this->doGetObjects();
}
/***
 * utility function
 */
private function stripPrefixes( Array &$array ){
	foreach( $array as &$item ){
		$item = substr( $item,4  );
	}
	return $array();
}
/**
 * 
 * inherited implementation method. Get all child objects
 * @param unknown_type $object
 */
abstract protected function doGetObjects(  );

abstract protected function doGetObject( $oid );
}
?>
